#include "config_signal_parse.h"
#include "parse_proto.h"
#include <thread>

using namespace DcAdr;

ConfigSignalParse::ConfigSignalParse(/* args */)
{
}

ConfigSignalParse::~ConfigSignalParse()
{
}

void ConfigSignalParse::loadConfig()
{
    ParseProto protoParser;
    protoParser.initProto();
    protoParser.parseSignalConfigJsonData(global_data::g_collect_config_buf);

    Log_Info("check config signal start...........................................");
    for (auto &topicParser : protoParser.m_protoSignalParser)
    {
        std::string topic = topicParser.first;
        google::protobuf::Message *parser = protoParser.getProtoMessageByTopic(topic);
        if (nullptr == parser)
        {
            Log_Info("Proto parser not found, topic: {}", topic);
            continue;
        }
        for (ProtoCondRuleSignalInfo_t &signal : topicParser.second)
        {
            if (!parseSignal(*parser, signal.name))
            {
                Log_Info("signal not found , name: {}", signal.signalName);
            }
            else
            {
                // Log_Info("signal found , name: {}", signal.signalName);
            }
        }
    }
    for (auto &topicParser : protoParser.m_protoSignalParser)
    {
        std::string topic = topicParser.first;
        if (!Contain_List(global_data::g_topics, topic))
        {
            Log_Info("topic not found : {}", topic);
        }
    }
    Log_Info("check config signal end...........................................");
}

bool ConfigSignalParse::parseSignal(const google::protobuf::Message &message, std::queue<std::string> &protoStruct)
{
    const google::protobuf::Descriptor *des = message.GetDescriptor();
    const google::protobuf::Reflection *ref = message.GetReflection();
    if (nullptr == des)
    {
        Log_Signal("Proto Descriptor is nullptr");
        return false;
    }
    if (nullptr == ref)
    {
        Log_Signal("Proto Reflection is nullptr");
        return false;
    }
    // Log_Signal("Message type: {}", message.GetTypeName());
    
    if (protoStruct.empty())
    {
        Log_ERROR("proto name queue empty.");
        return false;
    }

    //为了兼容嵌套message,获取首个判断
    std::queue<std::string> nameQueue = protoStruct;
    std::string name = nameQueue.front();
    nameQueue.pop();

    for (int i = 0; i < des->field_count(); i++)
    {
        const google::protobuf::FieldDescriptor *field = des->field(i); //      field 相当于此message下的信号， field->name(): 信号名
        // Log_Signal("field row, real name: {}   name: {}  - ", name, field->name(), field->DebugString());
        if (field == nullptr)
        {
            continue;
        }
        ///判断信号名
        if (field->name() != name)
        {
            continue;
        }
        if (field->is_repeated()) //不需要数组，数组需要单独的解析
        {
            continue;
        }
        switch (field->cpp_type())
        {
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT32:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_INT64:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_UINT32:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_UINT64:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_DOUBLE:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_FLOAT:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_BOOL:
        {
            return true;
        }
        break;
        //此类型无法转化  google::protobuf::EnumValueDescriptor
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_ENUM:
        {
            return true;
        }
        break;

        //暂时不支持 编译告警
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_STRING:
        {
            return true;
        }
        break;
        case google::protobuf::FieldDescriptor::CppType::CPPTYPE_MESSAGE:
        {
            //先判断是不是嵌套message，如果是，嵌套获取
            return parseSignal(ref->GetMessage(message, field), nameQueue);
        }
        break;
        default:
            break;
        }
    }
    return false;
}